package com.eugene.element;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.eugene.enums.EMaturity;
import com.eugene.interfaces.Calculable;
import com.eugene.interfaces.Functionable;

public class UnaryOperation<T extends Functionable> implements Serializable{
	private String unaryId;
	private T reference;
	private double coefficient;
	private double power;
	private double spread;
	private List<T> refs = new ArrayList<T>();
	
	private String refId;
	private EMaturity refMaturity;
	
	public UnaryOperation(){
	}
	
	public UnaryOperation(String id, T ref, double coefficient, double power, double spread){
		this.unaryId = id;
		this.reference = ref;
		this.coefficient =coefficient;
		this.power = power;
		this.spread = spread;
	}

	
	public String getUnaryId() {
		return unaryId;
	}

	public void setUnaryId(String unaryId) {
		this.unaryId = unaryId;
	}

	public T getReference() {
		return reference;
	}

	public void setReference(T reference) {
		this.reference = reference;
	}

	public double getCoefficient() {
		return coefficient;
	}

	public void setCoefficient(double coefficient) {
		this.coefficient = coefficient;
	}

	public double getPower() {
		return power;
	}

	public void setPower(double power) {
		this.power = power;
	}

	public double getSpread() {
		return spread;
	}

	public void setSpread(double spread) {
		this.spread = spread;
	}

	public String getRefId() {
		return refId;
	}

	public void setRefId(String refId) {
		this.refId = refId;
	}

	public EMaturity getRefMaturity() {
		if(refMaturity == null){
			refMaturity = EMaturity.SPOT;
		}
		return refMaturity;
	}

	public void setRefMaturity(EMaturity refMaturity) {
		this.refMaturity = refMaturity;
	}

	@Override
	public boolean equals(Object other){
		return super.equals(other); 
	}
	@Override
	public int hashCode(){
		return super.hashCode();
	}
	
//	*************Biz Method***************
//	public double getOperatedValue(){
//		return getCoefficient()* Math.pow(reference.getValue(), getPower()) + getSpread();
//	}
	
	public <T extends Functionable> T getOperated(T rst){
		double tweaked;
		rst.getOperands().clear();
		List<Calculable> ref = reference.getOperands();
		
		for(Calculable aa: ref){
			tweaked =getCoefficient()* Math.pow(aa.getValue(), getPower()) + getSpread();
			aa.setValue(tweaked);
			rst.getOperands().add(aa);
		}
		return rst;
	}
	
//	public <T extends Functionable> T getOperated(){
//		T rst = (T)getReference();
//		double temp =getCoefficient()* Math.pow(reference.getValue(), getPower()) + getSpread();
//		rst.setValue(temp);
//		return rst;
//	}
	
//	******************Static Method***************************
	
	public <T extends Calculable> void getOperated(List<T> list, List<T> rst){
		double tweaked =0.0 ;
//		for(T aa: list){
//			tweaked =coefficient*Math.pow(aa.getValue(), power)+spread;
//			aa.setValue(tweaked);
//			rst.add(aa);
//		}
		for(int i=0; i<list.size();i++){
			tweaked =coefficient*Math.pow(list.get(i).getValue(), power)+spread;
			rst.get(i).setValue(tweaked);
		}
	}
}
